package com.sunwayhorizo.health.business.registries.person;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Set;

import javax.ejb.Stateless;

import org.jboss.seam.Component;
import org.jboss.seam.annotations.Name;

import com.sunwayhorizo.health.business.base.BaseManager;
import com.sunwayhorizo.health.business.dto.patad.empi.MedicalCardDTO;
import com.sunwayhorizo.health.business.dto.patad.empi.PatientBaseInfoDTO;
import com.sunwayhorizo.health.business.dto.registries.EntitysDTO;
import com.sunwayhorizo.health.business.registries.person.query.PersonQueryLocal;
import com.sunwayhorizo.health.common.DataTypeUtil;
import com.sunwayhorizo.health.common.DateUtil;
import com.sunwayhorizo.health.common.Hl7NullRemover;
import com.sunwayhorizo.health.common.ListUtil;
import com.sunwayhorizo.health.common.StrUtil;
import com.sunwayhorizo.health.hl7.common.Hl7Exception;
import com.sunwayhorizo.health.hl7.datatypes.AD;
import com.sunwayhorizo.health.hl7.datatypes.BAG_EN;
import com.sunwayhorizo.health.hl7.datatypes.BAG_TEL;
import com.sunwayhorizo.health.hl7.datatypes.CE;
import com.sunwayhorizo.health.hl7.datatypes.ED;
import com.sunwayhorizo.health.hl7.datatypes.II;
import com.sunwayhorizo.health.hl7.datatypes.common.ADXPImpl;
import com.sunwayhorizo.health.hl7.datatypes.common.CSImpl;
import com.sunwayhorizo.health.hl7.datatypes.common.ENImpl;
import com.sunwayhorizo.health.hl7.datatypes.common.TELImpl;
import com.sunwayhorizo.health.hl7.rim.Person;
import com.sunwayhorizo.health.hl7.vocabulary.EntityAddrPartType;
import com.sunwayhorizo.health.hl7.vocabulary.EntityAddrUse;
import com.sunwayhorizo.health.hl7.vocabulary.EntityCode;
import com.sunwayhorizo.health.hl7.vocabulary.EntityDeterminer;
import com.sunwayhorizo.health.hl7.vocabulary.EntityIICode;
import com.sunwayhorizo.health.hl7.vocabulary.EntityNamePartType;
import com.sunwayhorizo.health.hl7.vocabulary.EntityNameUse;
import com.sunwayhorizo.health.hl7.vocabulary.EntityStatus;
import com.sunwayhorizo.health.hl7.vocabulary.EntityTelPartType;
import com.sunwayhorizo.health.hl7.vocabulary.EntityTelUse;

@Name("PersonManager")
@Stateless
public class PersonManager extends BaseManager implements PersonManagerLocal
{

    // 新建一个人
    public Person newPerson(EntitysDTO entitysDTO) throws Hl7Exception
    {
        // 创建一个person实例
        CE ce = DataTypeUtil.getCE(EntityCode.PERSON.toString());
        Person person = getEntityFactory().newPerson(ce, EntityDeterminer.INSTANCE);
        // 设置person的状态
        person.setStatusCode(EntityStatus.ACTIVE);
        // 构建一个person
        converPersonInfo(person, entitysDTO);
        return person;
    }


    // 删除person
    public void delPerson(Person person) throws Hl7Exception
    {
        em.remove(person);
    }


    // 修改person
    public void modifyPerson(Person person, EntitysDTO entitysDTO) throws Hl7Exception
    {
        converPersonInfo(person, entitysDTO);
    }


    // 根据查询出的Person组装一个EntitysDTO集合
    public EntitysDTO converPersonInfo(Person person) throws Hl7Exception
    {
        if (person == null)
            return null;
        EntitysDTO entitysDTO = new EntitysDTO();
        return converPersonInfo(entitysDTO, person);
    }


    public EntitysDTO converPersonInfo(EntitysDTO entitysDTO, Person person) throws Hl7Exception
    {
        if (person == null)
            return null;
        entitysDTO.setPatientBaseInfo(constructorPatBaseInfo(person));

        entitysDTO.setListMedicalCard(constructorMedicalCardList(person));

        Hl7NullRemover.removeHl7Null(entitysDTO);
        return entitysDTO;
    }


    // 组装一个List<EntitysDTO>
    public List<EntitysDTO> converPersonInfoList(List<Person> list) throws Hl7Exception
    {
        if (ListUtil.isEmpty(list))
            return null;
        List<EntitysDTO> entitysDTOList = new ArrayList<EntitysDTO>();
        for (Person person : list)
        {
            entitysDTOList.add(converPersonInfo(person));
        }
        return entitysDTOList;
    }


    // 组装person证件信息
    public List<MedicalCardDTO> constructorMedicalCardList(Person person) throws Hl7Exception
    {
        List<MedicalCardDTO> medicalList = new ArrayList<MedicalCardDTO>();
        for (EntityIICode iiCode : EntityIICode.values())
        {
            II ii = person.getId(iiCode);
            if (ii != null)
            {
                MedicalCardDTO infoPapersDTO = new MedicalCardDTO();
                infoPapersDTO.setId(ii.extension().toString());
                infoPapersDTO.setOffice(ii.iiSouce().toString());
                infoPapersDTO.setState(ii.iiState().toString());
                infoPapersDTO.setTypeDic(getDictionaryFactory().getDictionaryDTOByCe(ii.iiType()));
                medicalList.add(infoPapersDTO);
            }
        }
        return medicalList;
    }


    // 构造基本信息
    @SuppressWarnings("rawtypes")
    public PatientBaseInfoDTO constructorPatBaseInfo(Person person) throws Hl7Exception
    {
        if (person == null)
            return null;

        PatientBaseInfoDTO patientBaseInfo = new PatientBaseInfoDTO();

        // person RIM实体主键
        patientBaseInfo.setPersonId(String.valueOf(person.getEntityId()));

        if (person.getBirthTime() != null)
        {
            patientBaseInfo.setNatureBirthdate(StrUtil.formatNewStr(person.getBirthTime().toString()));
            patientBaseInfo.setNatureAge(DateUtil.getAge(person.getBirthTime().toDate()));
        }

        patientBaseInfo.setNatureImg(person.getDesc().integrityCheck().byteArray());
        if (!person.getDesc().literal().toString().equals("<Null:NullFlavor: NI>"))
        {
            patientBaseInfo.setNatureDescription(person.getDesc().stringValue());
        }
        // person名称
        BAG_EN names = person.getName();
        if (names != null)
        {
            List mList = names.toList();
            if (ListUtil.isNotEmpty(mList))
            {
                for (int i = 0; i < mList.size(); i++)
                {
                    ENImpl en = (ENImpl) mList.get(i);
                    Set set = (Set) en.use().toSet();
                    String code = "";
                    if (!set.isEmpty())
                    {
                        CSImpl use = (CSImpl) set.iterator().next();
                        code = use.code().toString();
                    }
                    if (code.equals(EntityNameUse.L.code().toString()))
                    {
                        patientBaseInfo.setNatureName(en.formatted().toString());
                    }
                    if (code.equals(EntityNameUse.PHON.code().toString()))
                    {
                        patientBaseInfo.setFullSpellCode(en.formatted().toString());
                    }
                    if (code.equals(EntityNameUse.SRCH.code().toString()))
                    {
                        patientBaseInfo.setPinyinCode(en.formatted().toString());
                    }
                    if (code.equals(EntityNameUse.SNDX.code().toString()))
                    {
                        patientBaseInfo.setWubiCode(en.formatted().toString());
                    }
                }
            }
        }

        // person地址
        AD addrs = person.getAddr();
        if (null != addrs)
        {
            List mList = addrs.toList();
            for (int i = 0; i < mList.size(); i++)
            {

                ADXPImpl ad = (ADXPImpl) mList.get(i);
                String type = ad.partType().code().toString();
                String addName = ad.literal().toString();
                if (addName.equals("<Null:NI>") || addName.equals("<Null:NullFlavor: NI>"))
                {
                    addName = "";
                }
                if (type.equals(EntityAddrPartType.HOMEADDRS.code().toString()))
                {
                    patientBaseInfo.setSocietyHomeAddress(addName);
                }
                if (type.equals(EntityAddrPartType.ZIPCODE.code().toString()))
                {
                    patientBaseInfo.setSocietyHomeCode(addName);
                }
            }
        }
        // person的联系方式
        BAG_TEL tels = person.getTelecom();
        if (null != tels)
        {
            List mList = tels.toList();
            for (int j = 0; j < mList.size(); j++)
            {
                TELImpl tel = (TELImpl) mList.get(j);
                CSImpl useCode = (CSImpl) tel.use().toSet().iterator().next();
                String use = useCode.code().toString();
                String telName = tel.scheme().code().toString();
                if (telName.equals("<Null:NI>") || telName.equals("<Null:NullFlavor: NI>"))
                {
                    telName = "";
                }
                if (use.equals(EntityTelUse.MC.code().toString()))
                {
                    patientBaseInfo.setSocietyMobile(telName);
                }
                if (use.equals(EntityTelUse.WP.code().toString()))
                {
                    patientBaseInfo.setSocietyPhone(telName);
                }
                if (use.equals(EntityTelUse.TMP.code().toString()))
                {
                    patientBaseInfo.setSocietyEmail(telName);
                }
            }
        }

        // 籍贯
        patientBaseInfo.setNativePlace(((getDictionaryFactory().getDictionaryDTOByCe(person.getOriginCodeEtsID())) != null ? (getDictionaryFactory()
            .getDictionaryDTOByCe(person.getOriginCodeEtsID())).getConceptCode() : ""));
        // 国籍
        patientBaseInfo.setNatureNationalityDic(getDictionaryFactory().getDictionaryDTOByCe(person.getNationalityCode()));
        // 婚史
        patientBaseInfo.setMerryFlagDic(getDictionaryFactory().getDictionaryDTOByCe(person.getMaritalStatusCode()));
        // 身份
        patientBaseInfo.setNatureIdentityDic(getDictionaryFactory().getDictionaryDTOByCe(person.getIdentityCode()));
        // 职业
        patientBaseInfo.setSocietyWorkDic(getDictionaryFactory().getDictionaryDTOByCe(person.getProfessionCode()));
        // 民族
        patientBaseInfo.setNatureNationDic(getDictionaryFactory().getDictionaryDTOByCe(person.getEthnicGroupCode()));
        // 性别
        patientBaseInfo.setNatureSexDic(getDictionaryFactory().getDictionaryDTOByCe(person.getAdministrativeGenderCode()));

        return patientBaseInfo;
    }


    @Override
    public Person findSamePerson(String personName, String sex, String birthDate) throws Hl7Exception
    {
        PersonQueryLocal personQuery = (PersonQueryLocal) Component.getInstance("PersonQuery");
        return personQuery.findSamePerson(personName, sex, birthDate);
    }


    // 构造person基本信息
    private void converPersonInfo(Person person, EntitysDTO entitysDTO) throws Hl7Exception
    {
        // 构造患者基本信息
        converPersonBaseInfo(person, entitysDTO.getPatientBaseInfo());

        // 构造Person Name信息
        converPersonNames(person, entitysDTO.getPatientBaseInfo());

        // 构建person地址信息
        converPersonAddrs(person, entitysDTO.getPatientBaseInfo());

        // 构建person联系信息
        converPersonTel(person, entitysDTO.getPatientBaseInfo());

        // 构造person的字典信息
        converPersonDic(person, entitysDTO.getPatientBaseInfo());

        // 构造person的证件信息
        coverPersonIdentityCard(person, entitysDTO.getListMedicalCard());

    }


    private void converPersonNames(Person person, PatientBaseInfoDTO patientBaseInfo) throws Hl7Exception
    {
        // 名称
        if (!StrUtil.isEmpty(patientBaseInfo.getNatureName()))
        {
            String[] name = { patientBaseInfo.getNatureName() };
            String[] type = { EntityNamePartType.FULL_NAME.code().toString() };
            String nameUseCode = EntityNameUse.L.code().toString();
            BAG_EN bagName = DataTypeUtil.getBagEN(name, type, nameUseCode);
            person.setName(bagName);
        }

        // 简码
        if (!StrUtil.isEmpty(patientBaseInfo.getPinyinCode()))
        {
            String[] name = { patientBaseInfo.getPinyinCode() };
            String[] type = { EntityNamePartType.SEARCH.code().toString() };
            String useCode = EntityNameUse.SRCH.code().toString();
            BAG_EN bagPing = DataTypeUtil.getBagEN(name, type, useCode);
            person.setName(bagPing);
        }
        // 五笔码
        if (!StrUtil.isEmpty(patientBaseInfo.getWubiCode()))
        {
            String[] name = { patientBaseInfo.getWubiCode() };
            String[] type = { EntityNamePartType.SOUNDEX.code().toString() };
            String useCode = EntityNameUse.SNDX.code().toString();
            BAG_EN bagPing = DataTypeUtil.getBagEN(name, type, useCode);
            person.setName(bagPing);
        }
        // 拼音码
        if (!StrUtil.isEmpty(patientBaseInfo.getFullSpellCode()))
        {
            String[] ping = { patientBaseInfo.getFullSpellCode() };
            String[] pingType = { EntityNamePartType.PHON.code().toString() };
            String pingUseCode = EntityNameUse.PHON.code().toString();
            BAG_EN bagPing = DataTypeUtil.getBagEN(ping, pingType, pingUseCode);
            person.setName(bagPing);
        }
    }


    // 构建person地址
    private void converPersonAddrs(Person person, PatientBaseInfoDTO patientBaseInfo) throws Hl7Exception
    {
        String[] addr = new String[2];
        if (!StrUtil.isEmpty(patientBaseInfo.getSocietyHomeAddress()))
        {
            addr[0] = StrUtil.removeNull(patientBaseInfo.getSocietyHomeAddress());
        }
        else
        {
            addr[0] = null;
        }
        if (!StrUtil.isEmpty(patientBaseInfo.getSocietyHomeCode()))
        {
            addr[1] = StrUtil.removeNull(patientBaseInfo.getSocietyHomeCode());
        }
        else
        {
            addr[1] = null;
        }

        String[] addrPart = { EntityAddrPartType.HOMEADDRS.code().toString(), EntityAddrPartType.ZIPCODE.code().toString() };
        AD ad = DataTypeUtil.getAD(addr, addrPart, EntityAddrUse.H.code().toString());
        person.setAddr(ad);
    }


    // 构建person的联系方式
    private void converPersonTel(Person person, PatientBaseInfoDTO patientBaseInfo) throws Hl7Exception
    {
        String[] address = new String[3];
        if (!StrUtil.isEmpty(patientBaseInfo.getSocietyMobile()))
        {
            address[0] = StrUtil.removeNull(patientBaseInfo.getSocietyMobile());
        }

        if (!StrUtil.isEmpty(patientBaseInfo.getSocietyPhone()))
        {
            address[1] = StrUtil.removeNull(patientBaseInfo.getSocietyPhone());
        }

        if (!StrUtil.isEmpty(patientBaseInfo.getSocietyEmail()))
        {
            address[2] = StrUtil.removeNull(patientBaseInfo.getSocietyEmail());
        }
        String scheme[] = { EntityTelPartType.MOBILE_PHONE.code().toString(), EntityTelPartType.TELCOM_PHONE.code().toString(),
                EntityTelPartType.TELCOM_EMAIL.code().toString() };
        Calendar startTime = GregorianCalendar.getInstance();
        startTime.set(Calendar.HOUR, 9);
        Calendar endTime = startTime;
        endTime.set(Calendar.HOUR, 17);
        Date low = startTime.getTime();
        Date high = endTime.getTime();
        Date useablePeriod[][] = { { low, high }, { low, high }, { low, high } };
        String telUseCode[] = { EntityTelUse.MC.code().toString(), EntityTelUse.WP.code().toString(), EntityTelUse.TMP.code().toString() };
        BAG_TEL bagTel = DataTypeUtil.getBAG_TEL(address, scheme, useablePeriod, telUseCode);
        person.setTelecom(bagTel);
    }


    // 构建person字典信息

    private void converPersonDic(Person person, PatientBaseInfoDTO patientBaseInfo) throws Hl7Exception
    {
        person.setOriginCodeEtsID(DataTypeUtil.getCE(patientBaseInfo.getNativePlace()));
        log.info("构造籍贯");

        CE nationality = getDictionaryFactory().getCeByDictionaryDTO(patientBaseInfo.getNatureNationalityDic());
        person.setNationalityCode(nationality);
        log.info("构造国籍");

        CE merryFlag = this.getDictionaryFactory().getCeByDictionaryDTO(patientBaseInfo.getMerryFlagDic());
        person.setMaritalStatusCode(merryFlag);
        log.info("构造婚史");

        CE identity = this.getDictionaryFactory().getCeByDictionaryDTO(patientBaseInfo.getNatureIdentityDic());
        person.setIdentityCode(identity);
        log.info("构造身份");

        CE vocation = this.getDictionaryFactory().getCeByDictionaryDTO(patientBaseInfo.getSocietyWorkDic());
        person.setProfessionCode(vocation);
        log.info("构造职业");

        CE nomen = this.getDictionaryFactory().getCeByDictionaryDTO(patientBaseInfo.getNatureNationDic());
        person.setEthnicGroupCode(nomen);
        log.info("构造民族");

        CE sexCe = getDictionaryFactory().getCeByDictionaryDTO(patientBaseInfo.getNatureSexDic());
        person.setAdministrativeGenderCode(sexCe);
        log.info("构造性别");
    }


    // 构建person基本信息
    private void converPersonBaseInfo(Person person, PatientBaseInfoDTO patientBaseInfo) throws Hl7Exception
    {

        // 保存二进制文件(如图片，大文本，音频，视频，附件等)
        if ((StrUtil.isNotEmpty(patientBaseInfo.getNatureDescription()))
                || (patientBaseInfo.getNatureImg() != null && patientBaseInfo.getNatureImg().length > 0))
        {
            ED ed = DataTypeUtil.getED(patientBaseInfo.getNatureDescription(), patientBaseInfo.getNatureImg());
            person.setDesc(ed);
        }

        // 出生日期
        if (StrUtil.isNotEmpty(patientBaseInfo.getNatureBirthdate()))
        {
            person.setBirthTime(DataTypeUtil.getTS(patientBaseInfo.getNatureBirthdate()));
        }

    }


    // 构造person证件信息
    private void coverPersonIdentityCard(Person person, List<MedicalCardDTO> listmedicalCard) throws Hl7Exception
    {
        if (ListUtil.isNotEmpty(listmedicalCard))
        {
            for (MedicalCardDTO infoPapersDTO : listmedicalCard)
            {
                if (StrUtil.isNotEmpty(infoPapersDTO.getId()) && infoPapersDTO.getTypeDic() != null
                        && StrUtil.isNotEmpty(infoPapersDTO.getTypeDic().getConceptCode()))
                {
                    for (EntityIICode iiCode : EntityIICode.values())
                    {
                        if (iiCode.getConceptCode() != null && iiCode.getConceptCode().equals(infoPapersDTO.getTypeDic().getConceptCode()))
                        {
                            CE certificateType = getDictionaryFactory().getCeByDictionaryDTO(infoPapersDTO.getTypeDic());
                            II papersID = DataTypeUtil.getII(infoPapersDTO.getId(), infoPapersDTO.getOffice(), infoPapersDTO.getState(),
                                certificateType, iiCode.toString());
                            person.setId(papersID);
                        }
                    }

                }
            }
        }
    }

}
